<template>
	<div class="lock-wrapper" :class="{
		'lock--active': parentlock,
	}" tabIndex="0">
	<slot></slot>
</div>
</template>

<script>
const upKeys = [
	33, // pageUp
	38,  // arrowUp
]
const downKeys = [
	32, // space
	34, // pageDown
	40,  // arrowDown
]
export default {
	name: 'dy-scroll-lock',

	componentName: 'dy-scroll-lock',

	props: {
		parentlock: {
			default: true,
			type: Boolean,
		},
		bodyLock: {
			default: false,
			type: Boolean,
		},
	},

	data () {
		return {
			pageY: 0,
			maxHeight: 0,
			scrollTop: 0,
			distanceY: '',
		}
	},

	watch: {
		bodyLock (val) {
			this.changeBLock(val)
		},
		parentlock (val) {
			this.changePLock(val)
		},
	},

	methods: {
		bindEvent () {
			this.$el.addEventListener('touchstart', this.onTouchStartHandler, false)
			this.$el.addEventListener('touchmove', this.onTouchMoveHandler, false)
		},

		removeEvent () {
			this.$el.removeEventListener('touchstart', this.onTouchStartHandler)
			this.$el.removeEventListener('touchmove', this.onTouchMoveHandler, false)
		},

		changeBLock (val) {
			if(val) {
				this.html.classList.add('body-noscroll')
			} else {
				this.html.classList.remove('body-noscroll')				
			}			
		},

		changePLock (val) {
			if(val) {
				this.bindEvent()		
			} else {
				this.removeEvent()				
			}			
		},		

		onTouchStartHandler (e) {
			const events = e.touches[0] || e
			this.pageY = events.pageY
			this.scrollTop = this.$el.scrollTop
			this.maxHeight = this.$el.scrollHeight - this.$el.clientHeight
		},

		onTouchMoveHandler (e) {
			if (this.maxHeight <= 0) {
				this.cancelScrollEvent(e)
				return;
			}
			const elScroll = this.$el
			// current scroll top
			const scrollTop = elScroll.scrollTop
			const events = e.touches[0] || e
			this.distanceY = events.pageY - this.pageY

			// top limit
			if (this.distanceY > 0 && scrollTop == 0) {
				this.cancelScrollEvent(e)
				return
			}
			// bottom limit
			if (this.distanceY < 0 && (scrollTop + 1 >= this.maxHeight)) {
				this.cancelScrollEvent(e)
				return
			}
		},		

		cancelScrollEvent (e) {
			e.stopImmediatePropagation()
			e.preventDefault()
			return false
		},

		handleEventDelta (e, delta) {
			const isDeltaPositive = delta > 0
			const el = this.$el
			const { scrollTop, scrollHeight, clientHeight } = el

			let shouldCancelScroll = false
			if (isDeltaPositive && delta > scrollHeight - clientHeight - scrollTop) {
					// bottom limit
					el.scrollTop = scrollHeight
					shouldCancelScroll = true
				} else if (!isDeltaPositive && -delta > scrollTop) {
					// top limit
					el.scrollTop = 0
					shouldCancelScroll = true
				}

				if (shouldCancelScroll) {
					this.cancelScrollEvent(e)
				}
			},
		},

		mounted () {
			this.html = document.querySelector('html')
			this.changeBLock(this.bodyLock)			
			this.changePLock(this.parentlock)			
		}		
	}
</script>

<style>
.lock-wrapper {
	outline: none;
}
.lock-wrapper.lock--active {
	-webkit-overflow-scrolling: touch;
}
.body-noscroll,
.body-noscroll body {
	overflow: hidden;
}
.body-noscroll body {
	position: relative;
}
</style>
